package com.elecbook.auth.config.authsecurity;

import com.alibaba.fastjson.JSON;
import com.elecbook.auth.model.dto.LoginDTO;
import com.elecbook.auth.service.WxLoginAuthService;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;


/**
 * description 添加一个自定义的支持器件
 *
 * @author zken
 * CreateDate 2024/11/2 16:03:12
 */
public class WxLoginUsernamePasswordAuthenticationProvider extends DaoAuthenticationProvider {

    // 跨越UserDetailService的直接实现类，直接使用wx的service更加直接。
    private final WxLoginAuthService wxLoginAuthService = new WxLoginAuthService();

    /**
     * description 重写函数注意事项，首先，根据获取的userDetail的信息进行返回验证，生成对应的token
     * 这是源代码中，返回authentication的一段代码
     * Object principalToReturn = user;
     * <p>
     * if (forcePrincipalAsString) {
     * principalToReturn = user.getUsername();
     * }
     * <p>
     * return createSuccessAuthentication(principalToReturn, authentication, user);
     *
     * @author zken
     * CreateDate 2024/11/2 16:55:42
     * <p>
     * 项目规范规定：
     * 所有的authentication参数传输，使用的都是对象字符串进行的传输，
     * 其中包含的实体是loginDTO实体
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String loginDtoStr = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
                : authentication.getName();

        LoginDTO loginDTO = JSON.parseObject(loginDtoStr, LoginDTO.class);
        String code = loginDTO.getWxCode();

        if (code.equals("NONE_PROVIDED")) {
            throw new UsernameNotFoundException("传入的用户code名称为空");
        }

        // 执行登录逻辑-调用userDetailService(这个service的设置在SecurityConfig需要进行指明）
        // 模仿retrieveUser，由于父类代码中获取user的方法是一个final方法，我们无法进行重写，所以直接自己自定义一个
        // 之心userService的方法
        UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(loginDtoStr);

        Object principalToReturn = loadedUser;

        return createSuccessAuthentication(principalToReturn, authentication, loadedUser);
    }

    /**
     * description 重写support方法
     *
     * @author zken
     * CreateDate 2024/11/2 16:03:03
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return (WxLoginUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }
}
